//Autor Pablo Escudero
package com.tangerine.sonar;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;

import android.annotation.SuppressLint;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.Parcelable;
//import android.os.Parcelable;
import android.os.RemoteException;
import android.util.Log;

public class BluetoothService extends Service {
	
	private Timer mTimer = new Timer();
	public int counter = 0;
	public int incrementBy = 1;
	private static boolean isRunning = false;
	private List<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
	public static final int MSG_REGISTER_CLIENT = 1;
	public static final int MSG_UNREGISTER_CLIENT = 2;
	public static final int MSG_SET_INT_VALUE = 3;
	public static final int MSG_SET_STRING_VALUE = 4;
	public static final int MSG_SET_STOP_SEND = 5;
	public static final int MSG_SET_START_SEND = 6;
	public static final int MSG_ESTADO_CONEXION = 7;
	public static final int MSG_ESTADO_BASTON =8;
	//private boolean bSend=false;
	private final Messenger mMessenger = new Messenger(new IncomingMessageHandler()); // Target we publish for clients to send messages to IncomingHandler.
	private static final String LOGTAG = "BluetoothService";
	
	//Variables Bluetooth
	BluetoothAdapter BTAdapter;
	BluetoothDevice BTDevice;
	public boolean SSFound=false; 
	private ArrayList<BluetoothDevice> mArrayListDispositivo;
	private static BluetoothSerialService mSerialService = null;
    // Message types sent from the BluetoothReadService Handler
    public static final int MESSAGE_STATE_CHANGE = 1;
    public static final int MESSAGE_READ = 2;
    public static final int MESSAGE_WRITE = 3;
    public static final int MESSAGE_DEVICE_NAME = 4;
    public static final int MESSAGE_TOAST = 5;
    
    // Key names received from the BluetoothChatService Handler
    public static final String DEVICE_NAME = "device_name";
    public static final String STRING = "string";
		
	@Override
	public void onCreate() {
		super.onCreate();
		Log.i(LOGTAG, "Service Started.");
		//mTimer.scheduleAtFixedRate(new MyTask(), 0, 100L);
		isRunning = true;	
		BTAdapter = BluetoothAdapter.getDefaultAdapter();
		mArrayListDispositivo = new ArrayList<BluetoothDevice>();
		mArrayListDispositivo.clear();
		IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
	    filter.addAction(BluetoothDevice.ACTION_UUID);
	    filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
	    filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
		registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
		
		//a este punto no hace falta verificar si el BT ya esta encendio o disponible
		// en caso de que no este disponible, el servicio nunca seria llamado
		
		//reemplazar el null por el handler de mensajes
		mSerialService = new BluetoothSerialService(this, mHandlerBT);
		
		BTAdapter.startDiscovery();

	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i(LOGTAG, "Received start id " + startId + ": " + intent);
		return START_STICKY; // Run until explicitly stopped.
	}

	@Override
	public IBinder onBind(Intent intent) {
		Log.i(LOGTAG, "onBind");
		return mMessenger.getBinder();
	}

	private void sendMessageToUI(String value,int type) {
		Iterator<Messenger> messengerIterator = mClients.iterator();		
		while(messengerIterator.hasNext()) {
			Messenger messenger = messengerIterator.next();
			try {
				// Send data as a String
				Bundle bundle = new Bundle();
				bundle.putString(STRING, value);
				Message msg = Message.obtain(null, type);
				msg.setData(bundle);
				messenger.send(msg);

			} catch (RemoteException e) {
				// The client is dead. Remove it from the list.
				mClients.remove(messenger);
			}
		}
	}

	public static boolean isRunning()
	{
		return isRunning;
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if (mTimer != null) {mTimer.cancel();}
		counter=0;
		//mNotificationManager.cancel(R.string.service_started); // Cancel the persistent notification.
		Log.i("MyService", "Service Stopped.");
		isRunning = false;
		unregisterReceiver(mReceiver);
        if (mSerialService != null)
        	mSerialService.stop();
	}

	/*private class MyTask extends TimerTask {
		@Override
		public void run() {
			//Log.i(LOGTAG, "Timer doing work." + counter);
			try {
				if(mSerialService != null)
				{
				

				}

			} catch (Throwable t) { //you should always ultimately catch all exceptions in timer tasks.
				Log.e("TimerTick", "Timer Tick Failed.", t);            
			}
		}		
	}*/

	@SuppressLint("HandlerLeak")
	private class IncomingMessageHandler extends Handler { // Handler of incoming messages from clients.
		@Override
		public void handleMessage(Message msg) {
			Log.d(LOGTAG,"handleMessage: " + msg.what);
			switch (msg.what) {
			case MSG_REGISTER_CLIENT:
				mClients.add(msg.replyTo);
				break;
			case MSG_UNREGISTER_CLIENT:
				mClients.remove(msg.replyTo);
				break;
			case MSG_SET_INT_VALUE:
				incrementBy = msg.arg1;
				break;
			case MSG_SET_STOP_SEND:
				//bSend = false;
				break;
			case MSG_SET_START_SEND:
				//bSend = true;
				break;
			default:
				super.handleMessage(msg);
			}
		}
	}

	// Create a BroadcastReceiver for ACTION_FOUND
	private final BroadcastReceiver mReceiver = new BroadcastReceiver() {

	    @Override
	    public void onReceive(Context context, Intent intent) {
	     String action = intent.getAction();
	     if(BluetoothDevice.ACTION_FOUND.equals(action)) {
	       BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
	       Log.d(LOGTAG,device.getName() + "\n" + device.getAddress());
           if(device.getName() != null)
		       if(device.getName().equals("SonarStick"))
	           {
	        	   SSFound=true;
	        	   Log.d(LOGTAG,"Dispositivo encontrado, cancelando busqueda...");
	        	   sendMessageToUI("SonarStick encontrado", MSG_ESTADO_CONEXION);
				   BTAdapter.cancelDiscovery();
				   BTDevice = device;
	           } 
	     } else {
	       if(BluetoothDevice.ACTION_UUID.equals(action)) {
	         BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
	         Parcelable[] uuidExtra = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
	         for (int i=0; i<uuidExtra.length; i++) {
	           Log.d(LOGTAG,"\n  Device: " + device.getName() + ", " + device + ", Service: " + uuidExtra[i].toString());
	         }
	       } else {
	         if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
	           Log.d(LOGTAG,"Empezando a buscar dispositivos");
	           sendMessageToUI("Buscando Dispositivo", MSG_ESTADO_CONEXION);
	         } else {
	           if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
				 Log.d(LOGTAG,"La busqueda de dispositivos finalizo");
				 sendMessageToUI("La busqueda ha finalizado", MSG_ESTADO_CONEXION);
				 if(BTDevice!=null)
				 {
					 Log.i("Encontrado", "Nombre:" + BTDevice.getName() + " MAC" + BTDevice.getAddress());
				 
				     //Controlar que se haya encontrado el baston
				 
				    if (mSerialService != null) {
				    	// Only if the state is STATE_NONE, do we know that we haven't started already
				    	if (mSerialService.getState() == BluetoothSerialService.STATE_NONE) {
				    		// Start the Bluetooth chat services
				    		mSerialService.start();
				    	}
				    }
               
				    // Get the BluetoothDevice object
	                BluetoothDevice device = BTAdapter.getRemoteDevice(BTDevice.getAddress());
	                // Attempt to connect to the device
	                mSerialService.connect(device); 
	                sendMessageToUI("true", MSG_ESTADO_BASTON);
	                //unregisterReceiver(mReceiver);
				 }
				 else
				 {
					 sendMessageToUI("SonarStick no encontrado", MSG_ESTADO_CONEXION);
					 sendMessageToUI("false", MSG_ESTADO_BASTON);
				 }
				
	           }
	         }
	       }
	      }
	    }
	};
	 /* public static void removeDuplicates(List<BluetoothDevice> list)  
	  {  
	    Set uniqueEntries = new HashSet();  
	    for (Iterator iter = list.iterator(); iter.hasNext(); ) {  
	      Object element = iter.next();  
	      if (!uniqueEntries.add(element)) // if current element is a duplicate,  
	        iter.remove();                 // remove it  
	    }  
	  } */

	//Inicio Conexion bluetooth
	// The Handler that gets information back from the BluetoothService
	    @SuppressLint("HandlerLeak")
		private final Handler mHandlerBT = new Handler() {
	    	
	        @Override
	        public void handleMessage(Message msg) {        	
	            switch (msg.what) {
	            case MESSAGE_STATE_CHANGE:
	                switch (msg.arg1) {
	                case BluetoothSerialService.STATE_CONNECTED:
	                	Log.d(LOGTAG,"Conectado..");
	                	break;
	                case BluetoothSerialService.STATE_CONNECTING:
	                	Log.d(LOGTAG,"Conectando..");
	                    break;
	                    
	                case BluetoothSerialService.STATE_LISTEN:
	                case BluetoothSerialService.STATE_NONE:
	                    break;
	                }
	                break;
	            case MESSAGE_WRITE:
	            	//Por las dudas lo dejo 
	                break;
              
	            case MESSAGE_READ:
	            	String sData;
	            	sData= msg.getData().getString(BluetoothService.STRING);
	            	Log.d(LOGTAG,sData);
					//Aca mandar la info necesaria a la application
					if( mSerialService.isRunning)
						{
						sendMessageToUI(sData,MSG_SET_STRING_VALUE);
						}
	                break;
           
	            case MESSAGE_DEVICE_NAME:
	                break;
	            case MESSAGE_TOAST:
	                break;
	            }
	        }
	    };
	/*Fin Conexion bluetooth*/

}
